package com.ahdms.es.gm.asn1.cipher;

import com.ahdms.es.util.ConvertorUtils;
import org.bouncycastle.asn1.*;

public class SM2Cipher extends ASN1Object {

    private ASN1Integer x;
    private ASN1Integer y;
    private DERBitString hash;
    private ASN1Integer length;
    private DERBitString cipher;

    public static SM2Cipher getInstance(Object obj) {
        if (obj instanceof SM2Cipher) {
            return (SM2Cipher) obj;
        }
        if (obj != null) {
            return new SM2Cipher(ASN1Sequence.getInstance(obj));
        }
        return null;
    }

    public SM2Cipher(
            ASN1Integer x,
            ASN1Integer y,
            DERBitString hash,
            ASN1Integer length,
            DERBitString cipher) {
        this.x = x;
        this.y = y;
        this.hash = hash;
        this.length = length;
        this.cipher = cipher;
    }

    public SM2Cipher(DERBitString string) {
        byte[] bytes = string.getBytes();
        if (bytes.length != 180) {
            throw new IllegalArgumentException("cipher must be 180 byte, actual length " + bytes.length);
        }
        byte[] xBytes = new byte[64];
        System.arraycopy(bytes, 0, xBytes, 0, xBytes.length);
        this.x = new ASN1Integer(xBytes);

        byte[] yBytes = new byte[64];
        System.arraycopy(bytes, 64, yBytes, 0, yBytes.length);
        this.y = new ASN1Integer(yBytes);

        byte[] hashBytes = new byte[32];
        System.arraycopy(bytes, 128, hashBytes, 0, hashBytes.length);
        this.hash = new DERBitString(hashBytes);

        byte[] lengthBytes = new byte[4];
        System.arraycopy(bytes, 160, lengthBytes, 0, lengthBytes.length);

        this.length = new ASN1Integer(ConvertorUtils.byteToInt(lengthBytes));

        byte[] cipherBytes = new byte[16];
        System.arraycopy(bytes, 164, cipherBytes, 0, cipherBytes.length);
        this.cipher = new DERBitString(cipherBytes);
    }


    protected SM2Cipher(ASN1Sequence seq) {
        this.x = ASN1Integer.getInstance(seq.getObjectAt(0));
        this.y = ASN1Integer.getInstance(seq.getObjectAt(1));
        this.hash = DERBitString.getInstance(seq.getObjectAt(2));
        this.length = ASN1Integer.getInstance(seq.getObjectAt(3));
        this.cipher = DERBitString.getInstance(seq.getObjectAt(4));
    }

    public ASN1Integer getX() {
        return x;
    }

    public ASN1Integer getY() {
        return y;
    }

    public DERBitString getHash() {
        return hash;
    }

    public ASN1Integer getLength() {
        return length;
    }

    public DERBitString getCipher() {
        return cipher;
    }

    @Override
    public ASN1Primitive toASN1Primitive() {
        ASN1EncodableVector seq = new ASN1EncodableVector();
        seq.add(x);
        seq.add(y);
        seq.add(hash);
        seq.add(length);
        seq.add(cipher);
        return new DERSequence(seq);
    }

}
